<html>
<head>
<title>MVTools</title>
<link rel="stylesheet" type="text/css" href="../../avisynth.css">
<!--
Automatically generated, don't change:
$Id: mvtools.htm,v 1.1 2005/10/03 16:31:31 macpaille Exp $ 
-->
</head>
<body>
<h1>MVTools</h1>
<h2>Abstract</h2>
<b>author:</b> Manao & Fizick
<br><b>version:</b> 0.9.9.1
<br><b>download:</b>  <a href="http://manao4.free.fr/">http://manao4.free.fr/</a><br>
<b>category:</b>  Misc Plugins<br>
<b>requirements:</b> YV12 Colorspace<br>
<b>license:</b> GPL
<hr>
<h2>Table of contents
</h2>
<ul>
  <li><a href="#mvtools">
I) About MVTools</a>
  </li>
  <li><a href="#functions">II) Function descriptions</a></li>
  <li><a href="#examples">III) Examples</a></li>
  <li><a href="#disclaimer">IV) Disclaimer (don't skip that part, but I don't
force you to learn it either)</a></li>
  <li><a href="#revisions">V) Revisions</a></li>
</ul>
<h2><a name="MVTools"></a>I) About MVTools
</h2>
<p>Collection of filters (MVDenoise, MVMask and
others) which uses motion vectors generated by this plugin.
</p>
<p>Note. Some motion interpolation functions (MVBlur, MVConvertFPS, MVInterpolate)
are not implemented in this version. Try use <a href="mvtools095.htm">older MVTools version 0.95</a>
if you needed them.
<h2><a name="functions"></a>II) Function descriptions
</h2>

<h3>Common parameters</h3>

<p>Filters that use motion vectors have common parameters. Those are the scene-change
detection thresholds, and the mmx / isse flags. They also use one or
several vectors stream, which are produced by <code>MVAnalyse</code>.
</p>
<p><var>int thSCD1</var> : threshold which decides whether a block has changed 
between the previous frame and the current one. When a block has changed, it 
means for me that motion estimation for him isn't relevant at all. It occurs 
for example at scene changes. So it is one of the thresholds used to tweak the 
scene changes detection engine. Default is 300. Raising it will lower the 
number of blocks detected as changed. The threshold is compared to the SAD (
sum of absolute difference, a value which says how good the motion estimation
was ) value. If you use 4x4 blocks, you should divide that value by 4.
</p>
<p><var>int thSCD2</var> : threshold which sets how many blocks have to change 
for the frame to be considered as a scene change. It is ranged from 0 to 255, 0 
meaning 0 %, 255 meaning 100 %. Default is 130 ( which means 51 % ).
</p>
<p><var>bool mmx</var> : flags which allows to disable mmx optimizations if set to false.
Default is true. If your computer doesn't support mmx optimizations, it will be
disabled by default anyway ( and you won't be able to activate them )</p>
<p><var>bool isse </var> : flags which allows you to disable isse optimizations. Default is
true, and it behaves just like <var>mmx</var>.

<h3>MVAnalyse</h3>

<p><code>MVAnalyse</code> (<var>clip, int "blksize", int "pel", int "level", int "search",
int "searchparam", bool "isb", int "lambda", bool "chroma", int "delta", int "idx"</var>)
</p>
<p><var>blksize</var> : Size of a block. It's either 4, 8 or 16 ( default is 8 ).
Larger blocks are less sensitive to noise, are faster, but also less accurate.</p>
<p><var>pel</var> : it is the accuracy of the motion estimation. 1 means a
precision to the pixel. 2 means a precision to half a pixel. Value can only be 1 or 2.
Default is 1.</p>
<p><var>level</var> : it is the number of levels not used in the hierarchal
analysis made while searching for motion vectors. The lower the better. It is
kept variable for study's purposes only. Default : 0.</p>
<p><var>search, ssearchparam</var> : <var>search</var> decides the type of search, and
<var>searchparam</var> is an additionnal setting for this search :</p>
<ul>
	<li><var>search </var>= 0 : 'OneTimeSearch'. <var>searchparam</var> is the step between
  each vectors tried ( if <var>searchparam</var> is superior to 1, step will be
  progressively refined ).</li>
	<li><var>search </var>= 1 : 'NStepSearch'. N is set by <var>searchparam</var>. It's the
  most well known of the MV search algorithm.</li>
  <li><var>search </var>= 2 : Logarithmic search, also named Diamond Search.
  <var>searchparam</var> is the	initial step search, there again, it is refined
  progressively. It's the default search ( with searchparam = 1 )</li>
  <li><var>search </var>= 3 : Exhaustive search, <var>searchparam</var> is the radius. It is
  slow, but it gives the best results, SAD-wise.</li>
</ul>
<p><var>isb</var> : allows to choose between a forward search ( between the
current frame and the previous one ) and a backward one ( between the current
frame and the following one ). <var>isb </var>= false means forward search (
<var>isb</var> stands for is backward ).</p>
<p><var>lambda</var> : set the coherence of the field of vectors. The higher,
the more coherent. However, if set too high, some 'true' motion vectors can be
missed. Default is 0, but values around 400 - 2000 are strongly recommended.</p>
<p><var>chroma</var> : set to true, it allows to take chroma into account when
doing the motion estimation. Default is false.
<p><var>delta</var> : set the frame interval between the reference frame and the current
frame. By default, it's 1, which means that the motion vectors are searched between the current frame
and the previous ( or next ) frame. Setting it to 2 will allow you to search mvs between the frame n and n-2
or n+2 ( depending on the <var>isb</var> setting ).</p>
<p><var>idx</var> : allows the filter to store the interpolation he made during the motion estimation,
in order them to be reused by another instance of the filter on the same clip. It allows for example,
when doing a forward & backward search on the same clip, to avoid to compute twice the bilinear interpolation,
if pel = 2. By default, a unique negative number is given ( unique for each filter ). If you use it,
you should always use positive values, and you should only use the same value for filters which work
on the same clip ( else, the analysis won't work properly ).</p>
<h3>MVCompensate</h3>

<p><code>MVCompensate</code> (<var>clip, clip "vectors", bool "scbehavior", int "mode", int "idx"</var>)
</p>
<p>Do a full motion compensation of the frame. It means that the blocks pointed 
by the mvs in the reference frame will be moved along the vectors to reach their places 
in the current frame.</p>
<p><var>scbehavior</var> ( by default true ), decide which frame will be kept on
a scene change. If true, the frame is left unchanged. Else, the reference frame is
copied into the current one.</p>
<p><var>mode</var> can be either 0 ( default ), 1 or 2. 0 means it uses the compensation made
during the mvs search. 1 means it recomputes that compensation ( because you may want to
apply vectors to a different clip that the one on which you searched ). 2 means it recomputes
the compensation, but it does it in-loop, meaning that the vectors will be applied to the last
frame computed. Results will be ugly, and that mode shouldn't be used except if you know
what you're doing.</p>
<p><var>idx</var> works the same way as <var>idx</var> in MVAnalysis. It is used only with <var>mode</var> = 1.

<h3>MVDenoise</h3>

<p><code>MVDenoise</code> (<var>clip, clip mvs [,...], bool "Y", bool "U", bool "V", int "thT", int "thSAD", int "thMV"</var>)
</p>
<p>Makes a temporal denoising with motion compensation, only on the luma. Reference
frames are motion compensated and then merged into the current frame.</p>
<p>The first threshold, <var>thT</var>, decides whether the pixel which comes from 
the previous or the following frame has to be taken into account. If this pixel 
differs more than <var>thT</var> from the pixel of the current frame, it is not used.</p>
<p>The second one, <var>thSAD</var>, decides whether the block has changed or 
not ( same principle as <var> thSCD1</var> ). If it has changed, the pixels aren't merged with those of 
the previous or following frame.</p>
<p><var>thMV</var> is the vector's length over which the block isn't used for
denoising.</p>
<p>Finally, <var>Y</var>, <var>U</var> and <var>V</var> tell which planes should be denoised.</p>
<p>Defaults are : <var>Y</var>, <var>U</var> and <var>V</var> are true, <var>thT</var> = 10, <var>thSAD</var> = 200 and <var>thMV</var>=30.</p>

<h3>MVMask</h3>

<p><code>MVMask</code> (<var>clip, clip "vectors", int "ml", float "gamma",
bool "showsad", int "Ysc"</var>)
</p>
<p>Creates a motion mask from the motion vectors' length. It builds a better 
mask than <a href="masktools.htm#motionmask"> MotionMask</a> ( <a href="masktools.htm"> 
MaskTools</a> ) because motion vectors are a lot more reliable than the 
algorithm of MotionMask.
</p>
<p>The mask is output only on the luma plane. 0 means no motion at all ( the 
length of the motion vector is null ), whereas 255 means maximum motion, and is 
defined by
<var>ml</var>. When the vector's length is superior or equal to ml, the output 
value is 255.
<var>gamma</var> is used to defined the relation length / value. 
<var>gamma</var>
= 1.0 implies a linear relation, whereas <var>gamma</var> = 2.0 gives a 
quadratic relation.</p>
<p><var>showsad</var> allows to build a mask of the SAD values instead of the
vectors' length. And finally, <var>Ysc</var> is the value taken by the mask on scene change
<p>Defaults are : <var>ml</var> = 100, <var>gamma</var> = 1.0, <var>showsad</var> = false and
<var>Ysc</var> = 0.</p>

<h3>MVShow</h3>

<p><code>MVShow</code> (<var>clip, clip "vectors", int "scale", int
"sil", int "tol", bool "showsad"</var>)
</p>
<p>Shows the motion vectors. <var>scale</var> allows to enlarge the motion
vectors, in order for example to gain in accuracy ( when
<var>pel</var> &gt; 1 and <var>scale</var> = 1, you can't see
a variation of less than one pixel ).
<var>sil</var> allows to see a different level of analysis ( when searching for 
motion vectors, a hierarchal analysis is done, and it may be interesting to see 
what happens at higher levels ).
<var>tol</var> is a tolerance threshold. If the distorsion induced by the 
motion vector is over tol the vector isn't shown.
Finally, <var>showsad</var> allows to show the mean SAD after compensating the
picture.</p>
<p>Defaults are : <var>scale</var> = 1, <var>sil</var> = 0, <var>tol</var> =
20000 and <var>showsad</var> = false ( which shows all vectors ).</p>

<h3>MVChangeCompensate</h3>
<p><code>MVChangeCompensate</code> (<var>clip vectors, clip</var>)</p> 
<p>Allows to change the compensation stored into the mvs stream.</p>

<h3>Deblock</h3>
<p><code>Deblock</code> (<var>clip, int "quant", int "aOffset", int "bOffset"</var>)</p>
<p>It does a deblocking of the picture, using the deblocking filter of h264. It doesn't
use motion vectors, however, it's usefull to deblock the result of <code>MVCompensate</code>.</p>
<p><var>quant</var> : the higher the quant, the stronger the deblocking. It can range from 0 to 51.</p>
<p><var>aOffset</var> : quant modifier to the blocking detector threshold. Setting it higher means than more
edges will deblocked.</p>
<p><var>bOffset</var> : another quant modifier, for block detecting and for deblocking's strength.
There again, the higher, the stronger.</p>
<p>Defaults are <var>quant</var> = 25, <var>aOffset</var> = <var>bOffset</var> = 0. If <var>quant</var> + 
<var>aOffset</var> is inferior to 16, the filter does nothing at all. The same goes for <var>quant</var> +
<var>bOffset</var>.</p>

<h3>MVIncrease</h3>
<p><code>MVIncrease</code> (<var>clip, clip "vectors", int "horizontal", int "vertical", int "idx"</var>)</p>
<p>It allows to use vectors computed on a reduced version of the clip in order
to make a compensation on a clip with the original size.</p>
<p><var>horizontal</var> is the horizontal ratio between the width of the clip
and the width of the reduced clip.</p>
<p><var>vertical</var> is the vertical ratio between the height of the clip
and the height of the reduced clip.</p>
<p><var>idx</var> works the same as in <code>MVAnalyse</code></p>

<h3>Corrector</h3>
<p><code>Corrector</code> (<var>clip analyse_0, clip output_0, clip analyse_i[, ...],
clip output_i[, ...], int "mode", int "th"</var>)
<p>This filter allows to construct a clip, pixels per pixels, from the output clips, based on the analyse clips.
There's two <var>mode</var>.</p>
<p><var>mode</var> = 0 : the output pixels whose collocated analyse pixels differs from the analyse_0 clip
by less than <var>th</var> are averaged to form the new pixel. If none are found, the output_0 pixel is chosen.</p>
<p><var>mode</var> = 1 : the output pixel whose collocated analyse pixels is the closest from analyse_0 clip
is chosen. If none differs by less than <var>th</var>, the output_0 pixel is chosen.</p>
<p>Defaults are <var>mode</var> = 0 and <var>th</var> = 10.</p>

<h3>MVDepan</h3>

<p><code>MVDepan</code> (<var>clip, clip "vectors", bool "zoom", bool "rot", float 
"pixaspect", float "error", bool "info"</var>)
</p>
<p>Get the motion vectors,&nbsp; estimate global motion&nbsp; and put data to 
output frame in special format for <code>DePan</code> plugin (by Fizick).</p>
<p>Inter-frame global motion (pan, zoom, rotation) is estimated by iterative 
procedure, with good blocks only.
</p>
<p>Rejected blocks: 1) near frame borders; 2) with big SAD (by <var>thSCD1</var> 
parameter); 3) with motion different from global.</p>
<p><i>zoom</i> and <i>rot</i> parameters switch zoom and rotation estimation, <var>
pixaspect </var>&nbsp;is pixel aspect (1.094 for standard PAL, 0.911 for 
standard NTSC),&nbsp; <var>error </var>is maximum mean motion difference.</p>
<p>The frame estimated global motion is switched to null for big motion error or 
at scene change&nbsp; (by <var>thSCD1, thSCD2</var> parameters).
</p>
<p><var>info</var> parameter allows to type global motion info for debug.
<p>Defaults are : <var>zoom</var> = true, <var>rot</var> = true, <var>pixaspect</var> = 1.0,
<var>error</var> = 15.0, <i>info</i> = false.</p>

<p>&nbsp;</p>

<h2><a name="examples"></a>III) Examples
</h2>
<p>To show the motion vectors ( forward ) :
</p>
<pre>vectors = source.MVAnalyse(isb = false)
return source.MVShow(vectors)</pre>
<p>To show the backward one :
</p>
<pre>vectors = source.MVAnalyse(isb = true)
return source.MVShow(vectors)</pre>
<p>To use MVMask :
</p>
<pre>vectors = source.MVAnalyse(isb = false)
return source.MVMask(vectors)</pre>
<p>To denoise :</p>
<pre>backward_vectors2 = source.MVAnalyse(isb = true, lambda = 1000, delta = 2)
backward_vectors1 = source.MVAnalyse(isb = true, lambda = 1000, delta = 1)
forward_vectors1 = source.MVAnalyse(isb = false, lambda = 1000, delta = 1)
forward_vectors2 = source.MVAnalyse(isb = false, lambda = 1000, delta = 2)
return source.MVDenoise(backward_vectors2, backward_vectors1, forward_vectors1, forward_vectors2, tht = 10, thSAD = 300)</pre>
<p>To deblock the compensation stored into a mvs stream</p>
<pre>vectors = source.MVAnalyse(isb = false, lambda = 1000)
compensation = source.MVCompensate(vectors, mode = 0)
compensation = compensation.Deblock()
vectors = vectors.MVChangeCompensate(compensation)</pre>

<p>To denoise with pel = 2, efficiently :</p>
<pre>backward_vectors2 = source.MVAnalyse(isb = true, lambda = 1000, delta = 2, pel = 2, idx = 1)
backward_vectors1 = source.MVAnalyse(isb = true, lambda = 1000, delta = 1, pel = 2, idx = 1)
forward_vectors1 = source.MVAnalyse(isb = false, lambda = 1000, delta = 1, pel = 2, idx = 1)
forward_vectors2 = source.MVAnalyse(isb = false, lambda = 1000, delta = 2, pel = 2, idx = 1)
return source.MVDenoise(backward_vectors2, backward_vectors1, forward_vectors1, forward_vectors2, tht = 10, thSAD = 300)</pre>

<p>To use MVIncrease : </p>
<pre>vectors = source.reduceby2().mvanalyse(isb = true)
return source.MVIncrease(vectors, horizontal = 2, vertical = 2)</pre>

<p>To use MVDepan with Depan plugin (DepanStabilize function example):</p>
<pre>vectors = source.MVAnalyse(isb = false)
globalmotion = source.MVDepan(vectors, pixaspect=1.094, thSCD1=400)
DepanStabilize(source, data=globalmotion, cutoff=2.0, mirror=15, pixaspect=1.094)
</pre>

<h2><a name="disclaimer"></a>IV) Disclaimer
</h2>
<p>This plugin is released under the GPL license. You must agree to the terms of
'Copying.txt' before using the plugin or its source code.
</p>

<h2><a name="revisions"></a>V) Revisions
</h2>
<p>0.9.9.1</p>
<ul>
<li>No need anymore of stlport_vcxxxx.dll</li>
</ul>
<p>0.9.9</p>
<ul>
<li>Filter added : Corrector</li>
<li>Filter added : MVIncrease</li>
<li>New available blocksize : 16</li>
<li>New parameter in MVAnalyse : <var>chroma</var></li>
<li>Changes in the core</li>
</ul>
<p>0.9.8.5</p>
<ul><li>MVCompensate changed : a new parameter, idx, which works as idx in MVAnalysis,
and which allows speed up when compensating the same frames several times.</li>
</ul>
<p>0.9.8.4</p>
<ul><li>ME takes into account the chroma now, as requested by tsp.</li>
</ul>
<p>0.9.8.3</p>
<ul><li>Added Corrector function, as requested by scharfi.</li>
</ul>
<p>0.9.8.2</p>
<ul><li>New function MVDepan (added by Fizick) for Depan plugin.</li>
</ul>
<p>0.9.8.1</p>
<ul><li>Several bugfixes</li>
</ul>
<p>0.9.8</p>
<ul><li>Yet another little changes in the filters' syntax. The core changed a lot,
in order to gain speed were it was possible. However, by default, the speed gain won't be
visible, you'll need to configure correctly the analysis filter through its "idx" 
parameter in order to gain speed ( in the mode "pel" = 2 ).</li>
<li>Bugfixes in MVDenoise, and chroma denoising in MVDenoise.</li>
<li>Now, the filters down the filter's chain tell to the analysis filter if they need
the compensation, so you don't have to worry about that at the analysing stage.</li>
</ul>
<p>0.9.7</p>
<ul><li>Yet again, a lot of rewriting. Interpolating filters are disabled ( for the moment ),
all the other filters work and should be considered as stable. Syntax has changed a lot,
and will change again before reaching 1.0 ( if it's reached one day ). Changes mainly affect
<code>MVAnalyse</code>. Two new filters : <code>Deblock</code> and <code>MVChangeCompensate</code>.
</li></ul>
<p>0.9.5
</p>
<ul>
  <li>Huge rewritting of the core engine. Vectors are now searched with a
   precision up to the pixel ( because no other filters can use yet more
   precise vectors, except MVShow ). The search engine is now fast ( which
   doesn't mean necessarily that the filters which use it are fast )</li>
   <li>A new parameter for MVAnalyse : lambda. See the documentation of the
   filter to see how it works</li>
   <li>MVDenoise works better.</li>
</ul>
<p>0.9.4
</p>
<ul>
  <li>Vectors can be saved to a file. In order to do so, add the parameter 
filename="C:\foo.bar" to the filter MVAnalyse. If the file doesn't exist, 
vectors will be saved into it. If it exists, vectors will be read from it. But, 
be warned :
    <ul>
      <li>The file for a whole movie will be around 500 MB</li>
      <li>Saving / reading from a file need for the moment a linear access to 
the frames, so it has to be used only when encoding the movie, not when doing 
random access in it.</li>
      <li>The speed gain is not as great as one may hope, because SADs can't be 
saved ( it would take too much space ) and so have to be recomputed.</li>
    </ul>
  </li>
  <li>The filter MVDenoise now works on 5 frames, and its parameters are now 
"thT" and "sadT" ( have a look in the documentation to see how they work ). It 
works nice ( very good for heavy denoising )</li>
  <li>The scene change detection thresholds have slightly changed. Now, a block 
has changed if its SAD it over thSCD1. The default for thSCD1 is 300, and for 
thSCD2 it is 130. It orks well ( better than the previous SCD engine ).<br>
  </li>
</ul>
<p>0.9.3</p>
<ul>
  <li>Last cleanings in the search of the motion vectors. It should be slightly 
faster</li>
  <li>More search parameters can be set by the user, especially the search 
algorithm. See the documentation</li>
  <li>Server / client implemented. You now first have to use MVAnalyse, and 
then the filter you want. Look at the documentation and at the examples I'll 
give alter.</li>
  <li>MVCompensate is separated from MVShow ( it's more logic that way ). For 
the moment, it doesn't move the chroma ( same behavior as MVShow in the latest 
releases )</li>
  <li>Some cleaning in MVBlur / MVInterpolate / MVConvertFPS, but still some 
work to do. Now, MVBlur blurs around the frame, not between the frame and the 
previous one.</li>
  <li>Half of the work is done for writing vectors to a file. But the resulting 
file will be large ( around 500 MB - 1 GB I guess ).</li>
  <li>MVDenoise is slightly faster ( at least it should )</li>
  <li>Copies are optimized inside the filter, thanks to avisynth's copy 
functions.</li>
  <li>MVShow can display the mean SAD of the compensation ( using showsad = 
true )</li>
</ul>
<p>0.9.2.1</p>
<ul>
  <li>MVInterpolate makes its come back.</li>
  <li>MVConvertFPS should work on the last few frames of the clip</li>
</ul>
<p>0.9.2</p>
<ul>
  <li>MVInterpolate doesn't exist anymore.</li>
  <li>MVBlur and MVConvertFPS have been improved. They also have got new 
parameters, have a look at the documentation.</li>
  <li>MVShow gets back its compensate mode ( MVShow(cm = true) )</li>
</ul>
<p>&nbsp;
</p>
</body>
</html>
